RK3399 模拟成鼠标触摸屏

您所在的位置:网站首页 触摸屏 鼠标中键 RK3399 模拟成鼠标触摸屏

RK3399 模拟成鼠标触摸屏

2023-12-21 10:18| 来源: 网络整理| 查看: 265

目标

利用3399 OTG口,连接电脑时能作为鼠标和触摸屏使用

应用场景

3399用在大屏显示设备上,支持HDMI输入,当外接笔记本电脑时,同时用USB数据线连接电脑,这时可以用大屏幕的触摸屏模拟成电脑的触摸屏,在大屏幕上直接操作电脑。本质上就是3399模拟成一个hid设备,网上模拟成鼠标的参考资料较多,第一步先模拟成鼠标,第二步实现单点触摸,第三步实现多点复合(其实是系统会报告是否支持单点,多点,如果都不支持,就去模拟成鼠标,例如windows XP,这部分可以参考圈圈教你学usb第二版,这一步暂时未实现)

系统架构

除了在内核模拟hid设备以外,在应用层3399收到触摸事件后,需要把数据写入到hid设备,这部分比较简单,可以参考android getevent的实现。

系统平台

Android7.1

参考资料

android-keyboard-gadget开源项目 圈圈教你学usb

调试工具

圈圈书上推荐的Bus Hound USB Trace?

模拟成鼠标设备

这部分主要参考3288开源项目,手上刚好有一块firefly3288的板子,在3288上验证了没问题。原理方面圈圈已经讲得很清楚,这里贴一下鼠标的设备描述符。

static struct hidg_func_descriptor fdesc_hid= { ---.subclass = 1, /* No subclass / ---.protocol = 2, / Keyboard */ ---.report_length = 4, ---.report_desc_length = 52, ---.report_desc = { 0x05, 0x01, //Usage Page(Generic Desktop Controls) 0x09, 0x02, //Usage (Mouse) 0xa1, 0x01, //Collection (Application) 0x09, 0x01, //Usage (pointer) 0xa1, 0x00, //Collection (Physical) 0x05, 0x09, //Usage Page (Button) 0x19, 0x01, //Usage Minimum(1) 0x29, 0x05, //Usage Maximum(5) 0x15, 0x00, //Logical Minimum(1) 0x25, 0x01, //Logical Maximum(1) 0x95, 0x05, //Report Count(5) 0x75, 0x01, //Report Size(1) 0x81, 0x02, //Input(Data,Variable,Absolute,BitField) 0x95, 0x01, //Report Count(1) 0x75, 0x03, //Report Size(3) 0x81, 0x01, //Input(Constant,Array,Absolute,BitField) 0x05, 0x01, //Usage Page(Generic Desktop Controls) 0x09, 0x30, //Usage(x) 0x09, 0x31, //Usage(y) 0x09, 0x38, //Usage(Wheel) 0x15, 0x81, //Logical Minimum(-127) 0x25, 0x7F, //Logical Maximum(127) 0x75, 0x08, //Report Size(8) 0x95, 0x03, //Report Count(3) 0x81, 0x06, //Input(Data,Variable,Relative,BitField) 0xc0, //End Collection 0xc0 //End Collection ---} }; 鼠标测试程序

核心代码

char track[] = { 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, 50,50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, -50,-50, }; while (count) { for(i = 0; i< sizeof(track); i = i+2 ){ memset(report, 0x0, sizeof(report)); report[1] = track[i]; report[2] = track[i+1]; if (write(fd, report, 4) != 4) { perror(filename); return 1; } usleep(500000); } count--; }

注意3288和3399都适用 移植到3399 需要注意的是3288的内核是3.10的,3399的内核是4.x,启用了configfs,设备描述符的写法与原先有些不同。

模拟成触摸屏

触摸屏与鼠标的不同点是鼠标的上报值是相对坐标,触摸屏是绝对坐标,鼠标xy轴分别需要一个字节,而触摸屏一般为12bit即两个字节。这里遇到一个坑是我把上报总长度搞错了,3288依然可以运行,但3399就不行。

描述符如下

static struct hidg_func_descriptor fdesc_hid= { ---.subclass = 0, /* No subclass / ---.protocol = 0, / Mouse */ ---.report_length = 5, ---.report_desc_length = 56, ---.report_desc = { 0x05, 0x01, //Usage Page(Generic Desktop Controls) 0x09, 0x02, //Usage (Mouse) 0xa1, 0x01, //Collection (Application) 0x09, 0x01, //Usage (pointer) 0xa1, 0x00, //Collection (Physical) 0x05, 0x09, //Usage Page (Button) 0x19, 0x01, //Usage Minimum(1) 0x29, 0x05, //Usage Maximum(5) 0x15, 0x00, //Logical Minimum(1) 0x25, 0x01, //Logical Maximum(1) 0x95, 0x05, //Report Count(5) 0x75, 0x01, //Report Size(1) 0x81, 0x02, //Input(Data,Variable,Absolute,BitField) 0x95, 0x01, //Report Count(1) 0x75, 0x03, //Report Size(3) 0x81, 0x01, //Input(Constant,Array,Absolute,BitField) 0x05, 0x01, //Usage Page(Generic Desktop Controls) 0x09, 0x30, //Usage(x) 0x09, 0x31, //Usage(y) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) 0x35, 0x00, //Physical Minimum (0) 0x46, 0xff, 0x7f, //Physical Maximum(32767) 0x75, 0x10, //Report Size(16) 0x95, 0x02, //Report Count(2) 0x81, 0x02, //Input(Data,Variable,ABS) 0xc0, //End Collection 0xc0 //End Collection ---} }; 测试程序

这块代码主要参考圈圈教你学USB第二版,同样适合3288和3399 核心代码

void MoveTo(int x, int y) { //需要返回的5字节报告的缓冲 //Buf[0]的D0就是左键,D1就是右键,D2就是中键 //Buf[1]为X轴低字节,Buf[2]为X轴高字节, //Buf[3]为Y轴低字节,Buf[4]为Y轴高字节, char Buf[5]={0,0,0,0,0}; Buf[0] = 0x00; Buf[1] = x & 0xFF; Buf[2] = (x >> 8) & 0xFF; Buf[3] = y & 0xFF; Buf[4] = (y >> 8) & 0xFF; if (write(mFd, Buf, 5) != 5) { return; } usleep(50000); } ////////////////////////End of function////////////////////////////// /******************************************************************** 函数功能:画线段的函数。 入口参数:x:x轴坐标;y:y轴坐标 返 回:无。 备 注:无。 ********************************************************************/ void LineTo(int x, int y) { //需要返回的5字节报告的缓冲 //Buf[0]的D0就是左键,D1就是右键,D2就是中键 //Buf[1]为X轴低字节,Buf[2]为X轴高字节, //Buf[3]为Y轴低字节,Buf[4]为Y轴高字节, char Buf[5]={0,0,0,0,0}; Buf[0] = 0x01; //左键按下 Buf[1] = x & 0xFF; Buf[2] = (x >> 8) & 0xFF; Buf[3] = y & 0xFF; Buf[4] = (y >> 8) & 0xFF; if (write(mFd, Buf, 5) != 5) { return; } usleep(50000); } if(strstr(cmd, "a") != NULL) { printf("Draw Tri-angle begin\n"); MoveTo(2000, 1000); //移动到(2000,1000) LineTo(2000, 1000); //开始画线 LineTo(1000, 3000); //画线到(1000,3000) LineTo(3000, 3000); //画线到(3000,3000) LineTo(2000, 1000); //画线到(2000,1000) MoveTo(2000, 1000); //松开鼠标左键 printf("Draw Tri-angle end\n"); } else if(strstr(cmd, "l") != NULL) { printf("Draw line begin\n"); MoveTo(1000, 1000); //移动到(1000,1000) LineTo(1000, 1000); //开始画线 LineTo(3000, 3000); //画线到(3000,3000) MoveTo(3000, 3000); //松开鼠标左键 printf("Draw line end\n"); }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3